package com.xwj.service.Impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xwj.Enums.StatusInfoEnum;
import com.xwj.dao.RaCloudHourseDao;
import com.xwj.data.StaticData;
import com.xwj.dto.CloudHouseInfoDto;
import com.xwj.dto.CreateCloudHouseInfoDto;
import com.xwj.entity.RaCloudHourse;
import com.xwj.entity.ResponseInfoEntity;
import com.xwj.httpclient.HttpService;
import com.xwj.service.Interface.RaCloudHourseService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.URISyntaxException;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;

/**
 * Created by xuweijie on 2018/1/19.
 */
@Slf4j
@Service
@CacheConfig(cacheNames = "RaCloudHourseCache")
public class RaCloudHourseServiceImpl implements RaCloudHourseService {

    @Autowired
    private RaCloudHourseDao raCloudHourseDao;
    @Autowired
    private RaStatusInfoServiceImpl raStatusInfoService;
    @Autowired
    private HttpService httpService;

    private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();  //读写锁

    private Lock lock = readWriteLock.readLock();

    @Override
    @Cacheable(key = "#cacheName", unless = "#result.list.size() == 0")
    public PageInfo<RaCloudHourse> findAllCloudHouse(int pageIndex, int pageSize, String cacheName) {
        PageHelper.startPage(pageIndex, pageSize);
        lock.lock();
        try {
            String label = StatusInfoEnum.CloudHouse.getName();
            List<RaCloudHourse> raCloudHourseList = raCloudHourseDao.findAllCloudHouse();
            raCloudHourseList.forEach(raCloudHourse -> {
                Map<String, Object> map = new HashMap<>();
                map.put("label", label);
                map.put("type", raCloudHourse.getStatus());
                String status = raStatusInfoService.findOneStatus(map);
                raCloudHourse.setStatusStr(status);
            });
            PageInfo<RaCloudHourse> pageInfo = new PageInfo<>(raCloudHourseList);
            return pageInfo;
        } catch (Exception e) {
            log.error("RaCloudHourseService异常:", e);
            e.printStackTrace();
            return new PageInfo<>(Collections.emptyList());
        } finally {
            lock.unlock();
        }
    }

    @Override
    @Cacheable(key = "'findByConditionResult_'+#pageIndex +'_attr_'+#cloudHouseInfoDto.toString()", unless = "#result.list.size() == 0")
    public PageInfo<RaCloudHourse> findALLByCondition(int pageIndex, int pageSize, CloudHouseInfoDto cloudHouseInfoDto) {
        PageHelper.startPage(pageIndex, pageSize);
        lock.lock();
        try {
            String label = StatusInfoEnum.CloudHouse.getName();
            List<RaCloudHourse> raCloudHourseList = raCloudHourseDao.findALLByCondition(cloudHouseInfoDto);
            raCloudHourseList.forEach(raCloudHourse -> {
                Map<String, Object> map = new HashMap<>();
                map.put("label", label);
                map.put("type", raCloudHourse.getStatus());
                String status = raStatusInfoService.findOneStatus(map);
                raCloudHourse.setStatusStr(status);
            });
            PageInfo<RaCloudHourse> pageInfo = new PageInfo<>(raCloudHourseList);
            return pageInfo;
        } catch (Exception e) {
            log.error("RaCloudHourseService异常:", e);
            e.printStackTrace();
            return new PageInfo<>(Collections.emptyList());
        } finally {
            lock.unlock();
        }

    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
    public int deleteOneById(int cloudId) {
        try {
            return raCloudHourseDao.deleteOneById(cloudId);
        } catch (Exception e) {
            log.error("RaCloudHourseService异常:", e);
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public int deletebatchById(List<Integer> list) {
        try {
            return raCloudHourseDao.deletebatchById(list);
        } catch (Exception e) {
            log.error("RaCloudHourseService异常:", e);
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public int insertOne(RaCloudHourse raCloudHourse) {
        try {
            return raCloudHourseDao.insertOne(raCloudHourse);
        } catch (Exception e) {
            log.error("RaCloudHourseService异常:", e);
            e.printStackTrace();
            return 0;
        }
    }

    @Override
    @Cacheable(key = "'Location'+#lon+#lat")
    public String findOneByLocation(BigDecimal lon, BigDecimal lat) {
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("lon", lon);
            map.put("lat", lat);
            return raCloudHourseDao.findOneByLocation(map);
        } catch (Exception e) {
            log.error("RaCloudHourseService异常:", e);
            e.printStackTrace();
            return StringUtils.EMPTY;
        }
    }

    @Override
    @Cacheable(key = "'CloudId'+#lon+#lat")
    public Integer findCloudIdByLocation(BigDecimal lon, BigDecimal lat) {
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("lon", lon);
            map.put("lat", lat);
            return raCloudHourseDao.findCloudIdByLocation(map);
        } catch (Exception e) {
            log.error("RaCloudHourseService异常:", e);
            e.printStackTrace();
            return null;
        }
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public int updateOneByParam(CreateCloudHouseInfoDto cloudHouseInfoDto) {
        try {
            return raCloudHourseDao.updateOneByParam(cloudHouseInfoDto);
        } catch (Exception e) {
            log.error("RaCloudHourseService异常:", e);
            e.printStackTrace();
            return 0;
        }
    }

    public List<Integer> parseListInt(List<RaCloudHourse> raCloudHourses) {
        return raCloudHourses.stream().map(RaCloudHourse::getCloudId).collect(Collectors.toList());
    }

    public String parseString(List<Integer> integerList) {
        if (integerList.size() == 0 || integerList == null)
            return StringUtils.EMPTY;
        StringBuilder builder = new StringBuilder(integerList.size() * 32);
        boolean first = true;
        for (int id : integerList) {
            if (first)
                first = false;
            else
                builder.append(",");
            builder.append(id);
        }
        return builder.toString();
    }

    /**
     * 删除请求
     *
     * @param value
     * @return
     * @throws IOException
     * @throws URISyntaxException
     */
    public ResponseInfoEntity deleteRequest(Object value) throws IOException, URISyntaxException {
        Map<String, Object> params = new HashMap<>();
        params.put("key", StaticData.KEY);
        params.put("tableid", StaticData.CLOUD_TABLE_ID);
        params.put("ids", value);
        String res = httpService.doPost(StaticData.DELETE_DATA_FROM_CLOUD_URL, params);
        ResponseInfoEntity responseInfoEntity = JSON.parseObject(res, new TypeReference<ResponseInfoEntity>() {
        });
        return responseInfoEntity;
    }

    /**
     * 单次创建/更新
     *
     * @param cloudHouseInfoDto
     * @return
     * @throws IOException
     * @throws URISyntaxException
     */
    public ResponseInfoEntity createOrUpdateOneReuest(CreateCloudHouseInfoDto cloudHouseInfoDto) throws IOException, URISyntaxException {
        Map<String, Object> params = new HashMap<>();
        Map<String, Object> data = new HashMap<>();
        String url;
        if (StringUtils.isNotBlank(cloudHouseInfoDto.getId())) {
            url = StaticData.UPDATE_DATA_FROM_CLOUD_URL;
            data.put("_id", cloudHouseInfoDto.getId());
        } else
            url = StaticData.ADD_ONE_DATA_TO_CLOUD_URL;
        params.put("key", StaticData.KEY);
        params.put("tableid", StaticData.CLOUD_TABLE_ID);
        params.put("loctype", 1);
        data.put("_name", cloudHouseInfoDto.getName());
        data.put("_address", cloudHouseInfoDto.getAddress());
        data.put("_location", cloudHouseInfoDto.getLon() + "," + cloudHouseInfoDto.getLat());
        params.put("data", JSON.toJSONString(data));
        String res = httpService.doPost(url, params);
        ResponseInfoEntity responseInfoEntity = JSON.parseObject(res, new TypeReference<ResponseInfoEntity>() {
        });
        return responseInfoEntity;
    }

}
